package com.example.demo.util;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.key.Jsr310NullKeySerializer;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Objects;
import java.util.TimeZone;

/**
 * json工具类
 */
public class JsonUtils {
    public static final ObjectMapper DEFAULT_OBJECT_MAPPER;
    public static final String PATTERN = "yyyy-MM-dd HH:mm:ss";
    public static final String TIME_ZONE = "GMT+8";

    static {
        DEFAULT_OBJECT_MAPPER = new ObjectMapper();
        DEFAULT_OBJECT_MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        DEFAULT_OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // localDateTime格式化
        JavaTimeModule module = new JavaTimeModule();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(PATTERN).withZone(ZoneId.of(TIME_ZONE));
        module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeFormatter));
        module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFormatter));
        DEFAULT_OBJECT_MAPPER.registerModule(module);
        // date时间格式化
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(PATTERN);
        simpleDateFormat.setTimeZone(TimeZone.getTimeZone(ZoneId.of(TIME_ZONE)));
        DEFAULT_OBJECT_MAPPER.setDateFormat(simpleDateFormat);
        // 处理key是null
        DEFAULT_OBJECT_MAPPER.getSerializerProvider().setNullKeySerializer(new Jsr310NullKeySerializer());
        // 处理value是null
        DEFAULT_OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    }

    public static String toJsonStr(Object obj) {
        if (obj == null) {
            return null;
        }
        try {
            return DEFAULT_OBJECT_MAPPER.writeValueAsString(obj);
        } catch (Exception e) {
            throw new RuntimeException("对象转json字符串异常：" + obj.getClass().getName());
        }
    }

    public static <T> T toBean(String json, Class<T> clz) {
        if (json == null) {
            return null;
        }
        if (clz == String.class) {
            return (T) json;
        }
        try {
            return DEFAULT_OBJECT_MAPPER.readValue(json, clz);
        } catch (Exception e) {
            throw new RuntimeException("json字符串转对象异常：" + clz.getName());
        }
    }

    public static <T> T toBean(String json, TypeReference<T> typeReference) {
        if (json == null) {
            return null;
        }
        if (Objects.equals(typeReference.getType().getTypeName(), String.class.getName())) {
            return (T) json;
        }
        try {
            return DEFAULT_OBJECT_MAPPER.readValue(json, typeReference);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("json字符串转对象异常：" + typeReference.getType().getTypeName());
        }
    }

    public static <T> List<T> toList(String json, Class<T> clz) {
        if (json == null) {
            return null;
        }
        try {
            return DEFAULT_OBJECT_MAPPER.readerForListOf(clz).readValue(json);
        } catch (Exception e) {
            throw new RuntimeException("json字符串转对象数组异常：List -> " + clz.getName());
        }
    }
}
